package com.gwaeron.game;

// JFC
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

// GTGE
import com.golden.gamedev.engine.BaseIO;
import com.golden.gamedev.object.GameFont;
import com.golden.gamedev.object.Timer;

//TODO: need to have a set amount of lines per "box", and change boxes if there's more text! Right now it'll just go outside the box.
// 6 lines of text per box.
public class RPGDialog {

	GameFont font;
	BufferedImage box;
	BufferedImage arrow;
	BufferedImage portrait;

	String[] dialog; // This is the dialog as shown in the event files. Contains
						// things like %TIME_PLAYED not replaced by the actual
						// string.
	String[] tempDialog; // This is the dialog as shown in the game, i.e.,
							// placeholders such as %TIME_PLAYED replaced by
							// actual time played.
	int frame;
	int totalFrame;
	int startX;
	int availableWidth;
	Timer speed;
	boolean blink;
	boolean bottom;
	Timer blinkTimer;
	int totalRows;
	int currentRow;
	BaseIO bsIO;
	boolean endDialog;
	boolean boxFull;

	int y;

	StatTracker stats;

	public RPGDialog(GameFont font, BufferedImage box, BufferedImage arrow) {
		this.font = font;
		this.box = box;
		this.arrow = arrow;
		this.stats = StatTracker.get();
		this.portrait = null;
		this.availableWidth = Map.GAME_WIDTH;
		this.totalRows = 100;
		this.currentRow = 0;
		speed = new Timer(20);
		blinkTimer = new Timer(400);
	}

	public void setDialog(BaseIO bsIO, String[] dialog, boolean bottom,
			BufferedImage portrait) {
		this.bottom = bottom;
		this.bsIO = bsIO;
		this.portrait = portrait;
		if (portrait != null) {
			this.startX = 105;
			this.availableWidth = Map.GAME_WIDTH - 105 - 40;
		} else {
			this.startX = 20;
			this.availableWidth = Map.GAME_WIDTH - 40;
		}
		this.dialog = dialog;
		this.tempDialog = new String[dialog.length]; // So that dynamic
		for (int i = 0; i < dialog.length; i++)
			tempDialog[i] = dialog[i];
		endDialog = false;
		totalRows = tempDialog.length;
		currentRow = dialog.length;
		if(currentRow>6)currentRow=6;
		frame = totalFrame = 0;
		for (int i = 0; i < dialog.length && i<6; i++) { //Max. 6 lines per box.
			this.tempDialog[i] = StringHandler.handleString(bsIO,
					this.tempDialog[i], font, (portrait!=null));
			totalFrame += tempDialog[i].length(); //How many frames it should take to draw the box. One per letter.
			System.out.println("Width: " + font.getWidth(tempDialog[i])); //For debugging, prints the length of one line.
		}

		blink = false;

		y = (bottom == true) ? 320 : 0;
	}

	public void update(long elapsedTime) {
		if (!endDialog) {
			if (speed.action(elapsedTime)) {
				if (++frame >= totalFrame) {
					endDialog = true;
				}
			}

		} else {
			if (blinkTimer.action(elapsedTime)) {
				blink = !blink;
			}
		}
	}

	public void render(Graphics2D g) {
		// Composite old = g.getComposite();
		// g.setComposite(old);

		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
				(float) 0.95));
		// render the box
		g.drawImage(box, 0, y, null);
		g.drawImage(portrait, 6, y+6, null);
		if (endDialog) {
			for (int i = 0; i < tempDialog.length && i<6; i++) {
				font.drawString(g, tempDialog[i], startX, y + 17 + (i * 22));
			}

			if (!blink) {
				g.drawImage(arrow, 310, y + 146, null);
			}

		} else {
			// type dialog letter by letter
			int typing = frame;

			for (int i = 0; i < tempDialog.length && i < 6; i++) {
				if (typing > tempDialog[i].length()) {
					typing -= tempDialog[i].length();
					font.drawString(g, tempDialog[i], startX, y + 17 + (i * 22));

				} else {
					// last dialog in current rendering
					font.drawString(g, tempDialog[i].substring(0, typing),
							startX, y + 17 + (i * 22));
					break;
				}
			}
		}
	}

	public boolean next() {
		if(currentRow < totalRows){
			String[] nextArray = new String[tempDialog.length-currentRow];
			for(int i = 0; i<nextArray.length;i++){
				nextArray[i] = tempDialog[currentRow+i];
			}
			setDialog(bsIO, nextArray, bottom, portrait);
			return true;
		} else return false;
	}

	public void setBottom(boolean bottom){
		this.bottom = bottom;
		y = (bottom == true) ? 320 : 0;
	}
}